package org.example.study4;
/**
 * 在多个实例中使用单独的锁对象
 */

// 展示了 使用实例级别锁保护静态变量时的线程安全问题。
// 虽然 count 是静态变量（类级别共享），但锁对象 locker 是实例级别的，导致多个实例的线程使用不同的锁，无法保证同步，最终结果小于预期的 10 万。
public class Demo_406 {
    public static void main(String[] args) throws InterruptedException {
        // 初始化两个不同的 Counter406 实例
        Counter406 counter = new Counter406(); // 实例1
        Counter406 counter1 = new Counter406(); // 实例2

        // 创建两个线程，分别操作不同的实例
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                counter.increase(); // 线程1调用实例1的 increase()
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                counter1.increase(); // 线程2调用实例2的 increase()
            }
        });

        // 启动线程
        t1.start(); // 线程1操作实例1
        t2.start(); // 线程2操作实例2

        // 等待线程结束
        t1.join();
        t2.join();

        // 输出结果（counter.count 访问静态变量，但结果可能小于 10 万）
        System.out.println("count = " + counter.count);
    }
}


class Counter406 {
    public static int count = 0; // 静态变量，类级别共享

    // 实例级别的锁对象（每个 Counter406 实例有自己的 locker）
    Object locker = new Object();

    /**
     * 累加方法（使用实例锁对象同步）
     */
    public void increase() {
        synchronized (locker) { // 锁定当前实例的 locker
            count++; // 修改静态变量
        }
    }
}

// 运行：count = 94322  // 实际值随机，因线程调度而异


/*锁对象与共享变量的作用域不匹配
静态变量 count：属于类级别，所有实例共享。
实例锁 locker：每个 Counter406 实例有自己的 locker。
线程1调用 counter.increase()，锁定 counter 的 locker。
线程2调用 counter1.increase()，锁定 counter1 的 locker。
两个线程使用不同的锁对象，不存在锁竞争关系，可以同时进入同步块修改 count。*/


/*总结
核心问题：锁对象的作用域必须与共享变量的作用域一致。若共享变量是静态的，必须使用类级别锁或静态锁对象。
设计陷阱：实例级别的锁无法保护类级别的共享变量（当存在多个实例时）。
实际意义：在多线程编程中，必须明确锁的粒度和作用域，确保所有线程对共享资源的访问通过同一锁进行同步。
体现知识点：锁的作用域、静态变量的同步机制、竞态条件。*/
